/**************************************************************************
 * @name: homework.c
 * @brief: 作业
 * @date: 2025/02/13
 * @author: boluzs@163.com
 * @note:
 *      1.要求在程序中创建2个子线程A和B
 *      2.主线程创建2个子线程之后就终止
 *      3.子线程A实现获取触摸屏的坐标并输出
 *      4.子线程B实现获取ARM开发板的系统时间并通过TrueType显示在LCD屏
 * @version: 1.0.0
 * @Copyright (c) 2025 by boluzs@163.com, All Rights Reserved.
 **************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>

#include <pthread.h>
#include <unistd.h>
#include <linux/input.h>
#include "font.h"

#define LCD_DEV "/dev/fb0"
#define LCD_SIZE 800 * 480 * 4

typedef struct TouchData
{
    unsigned int ts_x;
    unsigned int ts_y;
    unsigned int page;
    int ts_fd;
} Td_t, *Td_p;

Td_t touch_data;
char date_str[32] = {0};
font *pft;
unsigned int *lcd_mp;

int Show_Font(unsigned int fontSize, u32 width, u32 height,
              u32 byteperpixel, color buf_c, s32 x, s32 y,
              char *text, color font_c, s32 maxWidth, int px, int py)
{
    fontSetSize(pft, fontSize);                                            // 字体大小
    bitmap *bm = createBitmapWithInit(width, height, byteperpixel, buf_c); // 申请缓存
    fontPrint(pft, bm, x, y, text, font_c, maxWidth);                      // 加载字体
    show_font_to_lcd(lcd_mp, px, py, bm);                                  // 刷新缓存
    destroyBitmap(bm);                                                     // 释放输出框内存
    return 0;
}

void *Touch_Task(void *arg)
{
    int x = 0, y = 0;
    struct input_event ts_event;

    for (;;)
    {
        int ret = read(touch_data.ts_fd, &ts_event, sizeof(ts_event));

        if (ts_event.type == EV_ABS && ts_event.code == ABS_X)
            x = ts_event.value;
        else if (ts_event.type == EV_ABS && ts_event.code == ABS_Y)
            y = ts_event.value;

        if (ts_event.type == EV_KEY && ts_event.code == BTN_TOUCH && ts_event.value == 0)
        {
            touch_data.ts_x = x;
            touch_data.ts_y = y;
            printf("触摸松开，坐标: X = %d, Y = %d\n", touch_data.ts_x, touch_data.ts_y);
        }
    }
}

void *Time_Task(void *arg)
{
    for (;;)
    {
        time_t timer = time(NULL);
        // 2.获取系统时间并转化为格式化字符串
        struct tm *Date = localtime(&timer);
        sprintf(date_str, "%.2d-%.2d-%.2d %.2d:%.2d:%.2d",
                Date->tm_year + 1900,
                Date->tm_mon + 1,
                Date->tm_mday,
                Date->tm_hour,
                Date->tm_min,
                Date->tm_sec);
        Show_Font(25, 200, 25, 4, getColor(0, 128, 89, 60), 0, 0, date_str, getColor(0, 255, 255, 255), 200, 600, 10);
        sleep(1);
    }
}

int main(int argc, char const *argv[])
{
    // 打开字库
    pft = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");

    pthread_t touch_thread;
    pthread_t time_thread;

    int retval = 404;                    // 用于记录主线程的终止状态
    pthread_t main_tid = pthread_self(); // 用于记录主线程的ID
    printf("I am mainthread ,my id = %ld\n", main_tid);

    // 打开lcd屏文件
    int lcd_fd = open(LCD_DEV, O_RDWR);

    // 映射lcd文件到内存
    lcd_mp = (unsigned int *)mmap(NULL, LCD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
                                  lcd_fd, 0);
    if (lcd_mp == MAP_FAILED)
    {
        fprintf(stderr, "mmap lcd error,errno = %d,%s\n", errno, strerror(errno));
        exit(-1);
    }

    // 创建触摸屏的线程
    pthread_create(&touch_thread, NULL, Touch_Task, (void *)&main_tid);
    // 创建时间的线程
    pthread_create(&time_thread, NULL, Time_Task, (void *)&main_tid);

    // 终止线程，就算终止的是主线程，也不会导致进程被终止
    pthread_exit((void *)&retval);

    munmap(lcd_mp, LCD_SIZE);
    return 0;
}
